package com.southwind.service;

import com.southwind.model.bo.*;
import com.southwind.util.IOUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.transaction.manager.AssembleTransactionProcessor;
import org.fisco.bcos.sdk.transaction.manager.TransactionProcessorFactory;
import org.fisco.bcos.sdk.transaction.model.dto.TransactionResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;

@Slf4j
@Service

@Data
public class RecordService {
  private static String ABI;
  private static String BINARY;

  @Value("${system.contract.recordAddress}")
  private String address;

  @Autowired
  private Client client;

  private AssembleTransactionProcessor txProcessor;

  private static synchronized void loadContractResources() {
    try {
      if (ABI == null) {
        ABI = IOUtil.readResourceAsString("abi/Record.abi");
        if (ABI == null || ABI.isEmpty()) {
          throw new IllegalStateException("Failed to load ABI resource");
        }
      }
      if (BINARY == null) {
        BINARY = IOUtil.readResourceAsString("bin/Record.bin");
      }
    } catch (Exception e) {
      log.error("Contract resource loading failed", e);
      throw new RuntimeException("Critical: Contract resources initialization failed", e);
    }
  }

  @PostConstruct
  public void init() {
    try {
      loadContractResources();
      this.txProcessor = TransactionProcessorFactory.createAssembleTransactionProcessor(
              this.client,
              this.client.getCryptoSuite().getCryptoKeyPair()
      );
      log.info("RecordService initialized successfully with contract at {}", address);
    } catch (Exception e) {
      log.error("RecordService initialization failed", e);
      throw new RuntimeException("RecordService initialization failed", e);
    }
  }

  public TransactionResponse checkIn(RecordCheckInInputBO input) throws Exception {
    return txProcessor.sendTransactionAndGetResponse(
            address,
            ABI,
            "checkIn",
            input.toArgs()
    );
  }

  public TransactionResponse checkOut(RecordCheckOutInputBO input) throws Exception {
    return txProcessor.sendTransactionAndGetResponse(
            address,
            ABI,
            "checkOut",
            input.toArgs()
    );
  }

  public TransactionResponse getRecords(RecordGetRecordsInputBO input) throws Exception {
    return txProcessor.sendTransactionAndGetResponse(
            address,
            ABI,
            "getRecords",
            input.toArgs()
    );
  }

  public TransactionResponse getAllRecords(RecordGetAllRecordsInputBO input) throws Exception {
    return txProcessor.sendTransactionAndGetResponse(
            address,
            ABI,
            "getAllRecords",
            input.toArgs()
    );
  }
}
